package top.wilsonlv.jaguar.oauth2.security.component;

import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import top.wilsonlv.jaguar.commons.data.encryption.util.EncryptionUtil;
import top.wilsonlv.jaguar.commons.web.util.WebUtil;
import top.wilsonlv.jaguar.oauth2.security.properties.JaguarOauth2SecurityProperties;
import top.wilsonlv.jaguar.security.model.SecurityUser;
import top.wilsonlv.jaguar.security.util.SecurityUtil;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import static top.wilsonlv.jaguar.oauth2.security.Oauth2SecurityConstant.*;

/**
 * @author lvws
 * @since 2022/3/31 0031
 */
@Component
@RequiredArgsConstructor
public class RestClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {

    private final JaguarOauth2SecurityProperties jaguarOauth2SecurityProperties;

    @Override
    public ClientHttpResponse intercept(@NonNull HttpRequest request, byte @NonNull [] body, @NonNull ClientHttpRequestExecution execution) throws IOException {
        String serverId = jaguarOauth2SecurityProperties.getServerId();
        String timestamp = String.valueOf(System.currentTimeMillis());
        String nonce = UUID.randomUUID().toString();

        HttpHeaders headers = request.getHeaders();

        Map<String, String[]> params = new HashMap<>();
        params.put(OPENFEIGN_PARAMETER_PRE + PARAMETER_SERVER_ID, new String[]{serverId});
        params.put(OPENFEIGN_PARAMETER_PRE + PARAMETER_TIMESTAMP, new String[]{timestamp});
        params.put(OPENFEIGN_PARAMETER_PRE + PARAMETER_NONCE, new String[]{nonce});
        for (String key : params.keySet()) {
            headers.add(key, params.get(key)[0]);
        }

        Map<String, String> queryParams = WebUtil.getParams(request.getURI());
        for (String key : queryParams.keySet()) {
            params.put(key, new String[]{queryParams.get(key)});
        }

        String raw = EncryptionUtil.sortParams(params);
        String rawMd5 = EncryptionUtil.md5AsHex(raw);

        String sign = EncryptionUtil.signRsa(rawMd5, jaguarOauth2SecurityProperties.getServerPrivateKey());
        headers.add(OPENFEIGN_PARAMETER_PRE + PARAMETER_SIGN, sign);

        SecurityUser currentUser = SecurityUtil.getCurrentUser();
        if (currentUser != null && currentUser.getTenantId() != null) {
            headers.add("tenantId", currentUser.getTenantId().toString());
        }

        return execution.execute(request, body);
    }
}
